package com.muje.android.toiletcard;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;

import android.content.Context;
import android.util.Log;

/**
 * A poker game object contains 1 set of cards.
 * 
 * @author yeang-shing.then
 * 
 */
public class Poker {

	static final int CARD_COUNT = 52;
	static final String TOILET_NUMBER = "7";
	static final String SAFETY_KEY_NUMBER = "10";
	static final String THUMBS_UP_NUMBER = "Q";
	static final String COMMANDER_NUMBER = "K";

	/**
	 * Collection of player in a match of game.
	 */
	public ArrayList<Player> Players;
	private int playerCount;
	/**
	 * A match of 52 poker cards collections.
	 */
	public ArrayList<Card> Cards;

	/**
	 * Current show card.
	 */
	public Card Current;
	/**
	 * Current index in collection of players.
	 */
	private int playerIndex;
	private ArrayList<Integer> realPlayerIndexes;

	private Random random;
	private Context context;

	/**
	 * Constructor.
	 */
	public Poker(Context context) {

		this.context = context;
		this.Cards = new ArrayList<Card>();
		this.Players = new ArrayList<Player>();
		this.realPlayerIndexes = new ArrayList<Integer>();
		this.playerCount = 0;

		this.random = new Random();
		reset();
	}

	/**
	 * Initialize all 52 poker cards.
	 */
	public void reset() {

		// clear all player own card history
		for (Player player : this.Players) {
			if (player != null) {
				player.Cards = new ArrayList<Card>();
			}
		}

		// define card
		// for id naming
		String[] ids = new String[] { "a", "b", "c", "d", "e", "f", "g", "h",
				"i", "j", "k", "l", "m" };
		int[] ruleIds = new int[] { R.string.rule1, R.string.rule2,
				R.string.rule3, R.string.rule4, R.string.rule5, R.string.rule6,
				R.string.rule7, R.string.rule8, R.string.rule9,
				R.string.rule10, R.string.rule11, R.string.rule12,
				R.string.rule13 };

		// for display text
		String[] numbers = new String[] { "A", "2", "3", "4", "5", "6", "7",
				"8", "9", "10", "J", "Q", "K" };
		String[] shapes = new String[] { "Spade", "Heart", "Club", "Diamond" };

		for (int i = 0; i < ids.length; i++) {

			String rule = context.getResources().getString(ruleIds[i]);
			for (int j = 0; j < 4; j++) {
				String prefix = ids[i];
				String suffix = Integer.toString(j + 1);

				String id = prefix + suffix;
				String text = numbers[i] + " " + shapes[j];
				this.Cards.add(new Card(id, text, rule));
			}
		}// end loops

		this.playerIndex = 0;
		// Collections.sort(this.Cards, new CardComparator());
		// this.Current = this.Cards.get(0);
	}

	/**
	 * Improve shuffle the card.
	 */
	public void shuffle() {

		// manual insert first card to other position
/*		Log.d("DEBUG", "get 0");
		Card hold = this.Cards.get(0);
		this.Cards.remove(0);
		this.Cards.add(hold);

		int time = Math.min(1, random.nextInt(7));// min 1 max 7
		Log.d("DEBUG", "shuffle " + time * 52 + " times");
		for (int i = 0; i < time * 52; i++) {
			int index = random.nextInt(this.Cards.size());
			Log.d("DEBUG", "get " + index);
			hold = this.Cards.get(index);
			this.Cards.remove(index);
			// insert at random position within collection
			this.Cards.add(random.nextInt(52), hold);
		}*/
		
		//TODO: longer press to shuffle longer of time
		ArrayList<Card> hold = (ArrayList<Card>) this.Cards.clone();
		this.Cards.clear();
		while(hold.size()>0) {
			int index = random.nextInt(hold.size());
			Card card = hold.get(index);
			hold.remove(index);
			this.Cards.add(card);
		}
		Log.d("DEBUG","After shuffle size: "+this.Cards.size());

		//Collections.reverse(this.Cards);
		int lastIndex = this.Cards.size() - 1;
		if(lastIndex > -1) this.Cards.get(lastIndex).IsEnd = true;
		// this.Current = this.Cards.get(0);
	}

	public void previous() {

		Log.d("DEBUG", "Previous");

		if (this.Players.size() > 0) {
			this.playerIndex--;
			this.playerIndex = Math.abs(this.playerIndex % playerCount);
		}

		int index = realPlayerIndexes.get(playerIndex);
		Player lastPlayer = this.Players.get(index);
		int lastIndex = lastPlayer.Cards.size() - 1;
		if (lastIndex >= 0) {
			Card hold = lastPlayer.Cards.get(lastIndex);
			lastPlayer.Cards.remove(lastIndex);

			this.Cards.add(0, hold);
			this.Current = this.Cards.get(0);
		}
	}

	/**
	 * TODO: refactor Next card action.
	 */
	public void next() {

		Log.d("DEBUG", "Next");

		// remove the card from card collection
		// then put it belong to the current player
		if (this.Current != null) {
			Card hold = this.Current;
			if (this.Cards.size() > 0)
				this.Cards.remove(0);
			if (realPlayerIndexes.size() > 0) {

				if (hold.Text.contains(THUMBS_UP_NUMBER)) removeAllThumbsup();
				if(hold.Text.contains(COMMANDER_NUMBER)) removePreviousCommander();
				
				int index = realPlayerIndexes.get(playerIndex);
				this.Players.get(index).Cards.add(hold);
			}
		}

		if (this.Cards.size() == 0) {
			this.Current.IsEnd = true;
		} else {
			this.Current = this.Cards.get(0);
			if (this.Players.size() > 0) {
				this.playerIndex++;
				this.playerIndex = Math.abs(this.playerIndex % playerCount);// this.Players.size();
			}
		}
	}

	/**
	 * Skip to next person.
	 */
	public void skip() {

		if (this.Players.size() > 0) {
			this.playerIndex++;
			this.playerIndex = Math.abs(this.playerIndex % playerCount);
		}
	}

	/**
	 * Add a player for a match of game.
	 * 
	 * @param player
	 */
	public void addPlayer(Player player) {

		if (player != null) {
			playerCount++;
			Log.d("DEBUG", "adding player " + player.Name);
			realPlayerIndexes.add(this.Players.size());
		}
		this.Players.add(player);
	}
	/**
	 * Remove this player maybe due to quit the game or drunk already.
	 * @param player
	 */
	public void removePlayer(Player player) {
		
		for(int i=this.Players.size()-1;i>=0;i--) {
			if(this.Players.get(i).Name == player.Name){
				this.Players.remove(i);
				return;
			}
		}
	}

	/**
	 * Reset thumbs up owner.
	 */
	private void removeAllThumbsup() {
		
		for (Player player : this.Players) {
			
			if(player != null) {
				for (int i = player.Cards.size() - 1; i >= 0; i--) {
					if (player.Cards.get(i).Text.contains(THUMBS_UP_NUMBER)) {
						player.Cards.remove(i);
					}
				}
			}
		}
	}
private void removePreviousCommander() {
		
		for (Player player : this.Players) {
			
			if(player != null) {
				for (int i = player.Cards.size() - 1; i >= 0; i--) {
					if (player.Cards.get(i).Text.contains(COMMANDER_NUMBER)) {
						player.Cards.remove(i);
						return;
					}
				}
			}
		}
	}

	@SuppressWarnings("unused")
	private int countRealPlayer() {

		int counter = 0;
		for (Player player : this.Players) {
			if (player != null)
				counter++;
		}

		return counter;
	}
}
